﻿
using System;

namespace CodingMuscles.Text.Regexp
{
    /// <summary>
    /// Builds a regular expression pattern
    /// </summary>
    public interface IRegexPatternBuilder
    {
        /// <summary>
        /// Adds a position anchor to the end of the current pattern
        /// </summary>
        /// <param name="anchor">The anchor to add</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(Anchor anchor);

        /// <summary>
        /// Adds a literal string to the end of the current pattern
        /// </summary>
        /// <param name="match">The literal match to add</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>Characters requiring it will be automatically escaped</remarks>
        IRegexPatternBuilder Match(string match);

        /// <summary>
        /// Adds a character to the end of the current pattern as a numeric value
        /// </summary>
        /// <param name="match">The numeric match to add</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>This value is added to the pattern as a hexadecimal or Unicode value</remarks>
        IRegexPatternBuilder Match(ushort match);

        /// <summary>
        /// Adds a character to the end of the current pattern as a numeric value for a number of instances
        /// </summary>
        /// <param name="match">The numeric match to add</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>This value is added to the pattern as a hexadecimal or Unicode value</remarks>
        IRegexPatternBuilder Match(ushort match, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a character to the end of the current pattern as a numeric value for a number of instances
        /// </summary>
        /// <param name="match">The numeric match to add</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>This value is added to the pattern as a hexadecimal or Unicode value</remarks>
        IRegexPatternBuilder Match(ushort match, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a literal character to the end of the current pattern
        /// </summary>
        /// <param name="match">The literal character to add</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>Characters requiring it will be automatically escaped</remarks>
        IRegexPatternBuilder Match(char match);

        /// <summary>
        /// Adds a literal character to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="match">The literal character to add</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>Characters requiring it will be automatically escaped</remarks>
        IRegexPatternBuilder Match(char match, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a literal character to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="match">The literal character to add</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        /// <remarks>Characters requiring it will be automatically escaped</remarks>
        IRegexPatternBuilder Match(char match, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a character class to the end of the current pattern
        /// </summary>
        /// <param name="class">The character class to add</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(CharacterClass @class);

        /// <summary>
        /// Adds a character class to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="class">The character class to add</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(CharacterClass @class, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a character class to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="class">The character class to add</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(CharacterClass @class, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a character set to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the set</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(Action<ICharacterSetPatternBuilder> builder);

        /// <summary>
        /// Adds a character set to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the set</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(Action<ICharacterSetPatternBuilder> builder, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a character set to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the set</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Match(Action<ICharacterSetPatternBuilder> builder, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a non-matching character set to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the character set</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder NotMatch(Action<ICharacterSetPatternBuilder> builder);

        /// <summary>
        /// Adds a non-matching character set to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the character set</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder NotMatch(Action<ICharacterSetPatternBuilder> builder, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a non-matching character set to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the character set</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder NotMatch(Action<ICharacterSetPatternBuilder> builder, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a group to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder);

        /// <summary>
        /// Adds a group to the current position for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a group to the current position for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder, int minInstances, int maxInstances);

        /// <summary>
        /// Adds a group to the end of the current pattern
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <param name="capture">False if the strings captured in this group are of no interest; otherwise true</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder, bool capture);

        /// <summary>
        /// Adds a group to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <param name="capture">False if the strings captured in this group are of no interest; otherwise true</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder, int instances, Quantifier quantifier, bool capture);

        /// <summary>
        /// Adds a group to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="builder">The builder for creating the group pattern</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <param name="capture">False if the strings captured in this group are of no interest; otherwise true</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(Action<IRegexPatternBuilder> builder, int minInstances, int maxInstances, bool capture);

        /// <summary>
        /// Adds a named group to the end of the current pattern
        /// </summary>
        /// <param name="name">The name of the group</param>
        /// <param name="builder">A builder for creating the named-group pattern</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(string name, Action<IRegexPatternBuilder> builder);

        /// <summary>
        /// Adds a named group to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="name">The name of the group</param>
        /// <param name="builder">A builder for creating the named-group pattern</param>
        /// <param name="instances">The number of instances that must match</param>
        /// <param name="quantifier">Specifies if the number of instances is an exact amount or a minimum</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(string name, Action<IRegexPatternBuilder> builder, int instances, Quantifier quantifier = Quantifier.Exactly);

        /// <summary>
        /// Adds a named group to the end of the current pattern for a number of instances
        /// </summary>
        /// <param name="name">The name of the group</param>
        /// <param name="builder">A builder for creating the named-group pattern</param>
        /// <param name="minInstances">The minimum number of instances to match, inclusive</param>
        /// <param name="maxInstances">The maximum number of instances to match, inclusive</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Group(string name, Action<IRegexPatternBuilder> builder, int minInstances, int maxInstances);

        /// <summary>
        /// Adds an alternate to the end of the current pattern
        /// </summary>
        /// <param name="leftHandBuilder">Builder for creating the left hand side of the alternate pattern</param>
        /// <param name="rightHandBuilder">Builder for creating the right hand side of the alternate pattern</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Alternate(Action<IRegexPatternBuilder> leftHandBuilder, Action<IRegexPatternBuilder> rightHandBuilder);

        /// <summary>
        /// Adds a comment to the end of the current pattern
        /// </summary>
        /// <param name="comment">The arbitrary comment</param>
        /// <returns>A reference to this object after it is modified</returns>
        IRegexPatternBuilder Comment(string comment);
    }
}
